Tarea 1
- Nombre: Mateo Orozco Baldovino
- Especializacion en Estadistica Aplicada UTB
- La informacion puede ser encontrada en el siguiente repositorio https://github.com/TheMaorba/DataMining/tree/main/Tarea1
Punto 1:¶
# Importando librerias para analizar los datos
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
%matplotlib inline
img = cv.imread('D:\Documentos\Especialidad\DataMining\Tarea1\imagenpajaros.jpg')
print("The shape of image is =", np.shape(img))
The shape of image is = (1365, 2048, 3)
plt.figure(figsize=(8,9))
plt.imshow(img)
plt.show()
from skimage import io, color
img2=cv.cvtColor(img,cv.COLOR_BGR2RGB)
plt.figure(figsize=(8,9))
plt.imshow(img2)
plt.show()
img3=cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
plt.figure(figsize=(8,9))
plt.imshow(img3)
plt.show()
r,g,b=cv.split(img2)
plt.figure(figsize=(28,19))
plt.subplot(131)
im=plt.imshow(b,cmap="Blues")
plt.colorbar(im,fraction=0.029, pad=0.04)
plt.subplot(132)
im=plt.imshow(r,cmap="Reds")
plt.colorbar(im,fraction=0.029, pad=0.04)
plt.subplot(133)
im=plt.imshow(g,cmap="Greens")
plt.colorbar(im,fraction=0.029, pad=0.04)
plt.show()
plt.figure(figsize=(8,6))
plt.hist(b.ravel(),bins=256,range=(0,256),color='b',label='blue')
plt.hist(g.ravel(),bins=256,range=(0,256),color='g',label='green')
plt.hist(r.ravel(),bins=256,range=(0,256),color='r',label='red')
plt.legend()
plt.show()
Canal rojo La distribución roja se extiende desde valores bajos pero presenta un pico muy pronunciado alrededor de intensidades cercanas a 140‑160, con una caída progresiva hacia la derecha, lo que indica que la mayoría de los píxeles tienen niveles de rojo medios y relativamente parecidos entre sí. Esto concuerda con la menor varianza y coeficiente de variación que observaste, lo que hace que el canal rojo sea el más uniforme en la imagen.
Canal verde El canal verde aparece desplazado a la derecha respecto al azul y bastante solapado con la parte alta del rojo, con máximos alrededor de 150‑180 y una cola que se extiende hacia valores más bajos. Esto refleja que buena parte de la imagen tiene verdes intensos o medios, pero con más dispersión que el rojo, consistente con su asimetría negativa más marcada.
Canal azul El azul tiene un comportamiento distinto: concentra muchos píxeles en intensidades bajas‑medias (aprox. 0‑120), con un pico notable cerca de 0 y luego una subida progresiva y más plana sin un máximo tan agudo como el rojo. Esto indica que hay abundancia de zonas muy oscuras en azul y una variación amplia, lo que se refleja en su coeficiente de variación más alto y en el hecho de que aporte gran parte del contraste cromático de la imagen.
# Calcule para cada arreglo las medidas de tendencia central, las medidas de dispersión y las medidas de simetría correspondientes, también las medidas de variabilidad o coeficiente de variabilidad o coeficiente de Pearson. Diga si las medidas son robustas o no.
def calcular_estadisticas(arreglo, nombre_color):
media = np.mean(arreglo)
mediana = np.median(arreglo)
moda = np.bincount(arreglo.ravel()).argmax()
varianza = np.var(arreglo)
desviacion_std = np.std(arreglo)
asimetria = (3 * (media - mediana)) / desviacion_std if desviacion_std != 0 else 0
coef_variacion = (desviacion_std / media) * 100 if media != 0 else 0
print(f"Estadísticas para el canal {nombre_color}:")
print(f"Media: {media}")
print(f"Mediana: {mediana}")
print(f"Moda: {moda}")
print(f"Varianza: {varianza}")
print(f"Desviación estándar: {desviacion_std}")
print(f"Asimetría (Coef. de Pearson): {asimetria}")
print(f"Coeficiente de variación: {coef_variacion}%")
print()
# Separar canales
b, g, r = cv.split(img)
# Llamar la función para cada canal
calcular_estadisticas(b, "Azul")
calcular_estadisticas(g, "Verde")
calcular_estadisticas(r, "Rojo")
Estadísticas para el canal Azul: Media: 101.71976443550705 Mediana: 102.0 Moda: 0 Varianza: 2455.638718818396 Desviación estándar: 49.55440160892265 Asimetría (Coef. de Pearson): -0.016965328329733857 Coeficiente de variación: 48.71659100266735% Estadísticas para el canal Verde: Media: 144.99946136167767 Mediana: 159.0 Moda: 163 Varianza: 2161.1804435478466 Desviación estándar: 46.48849797044261 Asimetría (Coef. de Pearson): -0.903484039034163 Coeficiente de variación: 32.06115218213437% Estadísticas para el canal Rojo: Media: 140.94886526860097 Mediana: 147.0 Moda: 149 Varianza: 1566.2797753570271 Desviación estándar: 39.576252669461105 Asimetría (Coef. de Pearson): -0.45869436770109145 Coeficiente de variación: 28.078447168795666%
Tendencia central (brillo por canal): El canal Azul tiene una media/mediana mucho más baja (media ≈ 101.7, mediana = 102) que Verde (media ≈ 145.0, mediana = 159) y Rojo (media ≈ 140.9, mediana = 147), lo que sugiere que la imagen contiene menos intensidad azul promedio y está más “cargada” hacia componentes verdes y rojas.
Forma de la distribución (asimetría): Los tres canales presentan asimetría negativa (Azul ≈ -0.017 casi simétrica, Verde ≈ -0.903 marcada, Rojo ≈ -0.459 moderada), indicando que hay una cola hacia valores bajos; esto es especialmente fuerte en Verde, donde la mediana (159) está bastante por encima de la media (~145), señal de presencia relevante de píxeles con intensidades verdes bajas que “jalan” la media hacia abajo.
Dispersión y estabilidad relativa (variabilidad): En términos absolutos, Azul es el más disperso (DE ≈ 49.55, var ≈ 2455.64), pero en términos relativos (coeficiente de variación) también es el más inestable (CV ≈ 48.7%) frente a Verde (CV ≈ 32.1%) y Rojo (CV ≈ 28.1%); esto significa que el canal azul varía mucho más respecto a su propio promedio, mientras que rojo es el más consistente.
# Punto 4
def clasificar_intensidad(canal):
# Crear un arreglo vacío del mismo tamaño para guardar las categorías
categorias = np.empty(canal.shape, dtype=object)
# Aplicar las reglas
categorias[canal <= 85] = "Oscuro"
categorias[(canal > 85) & (canal <= 170)] = "Medio"
categorias[canal > 170] = "Claro"
return categorias
# Separar canales RGB
b, g, r = cv.split(img2) # ya tienes img2 en formato RGB en tu notebook
# Clasificar cada canal
b_cat = clasificar_intensidad(b)
g_cat = clasificar_intensidad(g)
r_cat = clasificar_intensidad(r)
print("Ejemplo de canal Azul categorizado:")
print(b_cat)
print("Ejemplo de canal Verde categorizado:")
print(g_cat)
print("Ejemplo de canal Rojo categorizado:")
print(r_cat)
Ejemplo de canal Azul categorizado: [['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ... ['Claro' 'Claro' 'Claro' ... 'Medio' 'Medio' 'Medio'] ['Claro' 'Claro' 'Claro' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Claro' 'Claro' ... 'Medio' 'Medio' 'Medio']] Ejemplo de canal Verde categorizado: [['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ... ['Medio' 'Medio' 'Claro' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Claro' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio']] Ejemplo de canal Rojo categorizado: [['Medio' 'Medio' 'Medio' ... 'Oscuro' 'Oscuro' 'Oscuro'] ['Medio' 'Medio' 'Medio' ... 'Oscuro' 'Oscuro' 'Oscuro'] ['Medio' 'Medio' 'Medio' ... 'Oscuro' 'Oscuro' 'Oscuro'] ... ['Medio' 'Medio' 'Claro' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio'] ['Medio' 'Medio' 'Medio' ... 'Medio' 'Medio' 'Medio']]
Los criterios de clasificación que estás usando toman el valor de intensidad de cada píxel en un canal (un número entre 0 y 255 para imágenes de 8 bits) y lo convierten en una categoría cualitativa según tres rangos fijos de luminosidad. En tu función, cualquier valor menor o igual a 85 se etiqueta como “Oscuro”, de 86 a 170 como “Medio” y mayor que 170 como “Claro”, de modo que cada píxel azul, verde o rojo queda clasificado según cuánta luz aporta ese canal en ese punto. Estos umbrales dividen aproximadamente el rango total en tres tramos similares, lo que permite describir estadísticamente la imagen (por ejemplo, porcentaje de píxeles oscuros, medios o claros) sin trabajar directamente con los valores numéricos continuos.
# Ahora suponga que la escala de cada color, la cual es un número que va en el intervalo [0,255] usted la divide en [”Claro”, ”Medio”, ”Oscuro”], bajo un criterio que usted elabore. Construya un nuevo arreglo (para cada canal) con estos datos.
def categorizar_intensidad(canal):
categorias = np.empty(canal.shape, dtype=object)
categorias[canal < 85] = 'Oscuro'
categorias[(canal >= 85) & (canal < 170)] = 'Medio'
categorias[canal >= 170] = 'Claro'
return categorias
categorias_r = categorizar_intensidad(r)
categorias_g = categorizar_intensidad(g)
categorias_b = categorizar_intensidad(b)
# Función para graficar y analizar cada canal
def graficos_y_analisis(categorias, nombre_canal):
# Contar categorías
valores, conteo = np.unique(categorias, return_counts=True)
# ==== GRÁFICO DE TORTA ====
plt.figure(figsize=(6,6))
plt.pie(conteo, labels=valores, autopct='%1.1f%%')
plt.title(f"Distribución de intensidades - Canal {nombre_canal}")
plt.show()
# ==== GRÁFICO DE BARRAS ====
plt.figure(figsize=(7,5))
plt.bar(valores, conteo)
plt.title(f"Conteo de intensidades - Canal {nombre_canal}")
plt.xlabel("Categoría")
plt.ylabel("Cantidad de píxeles")
plt.show()
# ==== INTERPRETACIÓN AUTOMÁTICA ====
total = conteo.sum()
porcentajes = conteo / total * 100
print(f"\nInterpretación del canal {nombre_canal}:")
for val, p in zip(valores, porcentajes):
print(f" - {val}: {p:.2f}%")
# Análisis simple basado en predominio
dominante = valores[np.argmax(conteo)]
if dominante == "Claro":
print(f">>> El canal {nombre_canal} muestra una imagen luminosa en este color.")
elif dominante == "Medio":
print(f">>> El canal {nombre_canal} es equilibrado, sin extremos marcados.")
else:
print(f">>> El canal {nombre_canal} tiende a tonos oscuros y apagados.")
print("\n" + "-"*50 + "\n")
# Ejecutar para cada canal
graficos_y_analisis(b_cat, "Azul")
graficos_y_analisis(g_cat, "Verde")
graficos_y_analisis(r_cat, "Rojo")
Interpretación del canal Azul: - Claro: 13.73% - Medio: 77.98% - Oscuro: 8.29% >>> El canal Azul es equilibrado, sin extremos marcados. --------------------------------------------------
Interpretación del canal Verde: - Claro: 33.49% - Medio: 52.32% - Oscuro: 14.19% >>> El canal Verde es equilibrado, sin extremos marcados. --------------------------------------------------
Interpretación del canal Rojo: - Claro: 9.18% - Medio: 52.68% - Oscuro: 38.14% >>> El canal Rojo es equilibrado, sin extremos marcados. --------------------------------------------------
fig, axes = plt.subplots(3, 2, figsize=(10, 12))
canales = [b_cat, g_cat, r_cat]
nombres = ["Azul", "Verde", "Rojo"]
for i, (categorias, nombre) in enumerate(zip(canales, nombres)):
valores, conteo = np.unique(categorias, return_counts=True)
total = conteo.sum()
porcentajes = conteo / total * 100
# Gráfico de torta
ax_pie = axes[i, 0]
ax_pie.pie(conteo, labels=valores, autopct="%1.1f%%")
ax_pie.set_title(f"Distribución - Canal {nombre}")
# Gráfico de barras
ax_bar = axes[i, 1]
ax_bar.bar(valores, conteo)
ax_bar.set_title(f"Conteo - Canal {nombre}")
ax_bar.set_xlabel("Categoría")
ax_bar.set_ylabel("Cantidad de píxeles")
plt.tight_layout()
plt.show()
La imagen evidencia que, al clasificar los píxeles por intensidad en tres categorías (Claro, Medio y Oscuro), predomina claramente la categoría Medio en los tres canales RGB, lo que sugiere una imagen con brillo general mayormente intermedio y sin saturaciones extremas; este patrón es especialmente fuerte en el canal azul, donde “Medio” concentra cerca del 78% y los valores oscuros son bajos (~8%), indicando poca presencia de azules intensamente apagados o muy brillantes. En el canal verde la distribución es más equilibrada, con una proporción importante de “Claro” (~33.5%) además de “Medio” (~52.3%), lo cual apunta a zonas con componente verde relativamente alta (áreas más iluminadas o con tonalidades verdosas). En contraste, el canal rojo mantiene “Medio” como mayoritario (~52.7%) pero muestra una fracción elevada de “Oscuro” (~38.1%) y pocos “Claro” (~9.2%), lo que sugiere que muchas regiones tienen componente roja baja (sombras o ausencia de rojos brillantes), reforzando una composición cromática dominada por tonos medios con variación marcada entre canales.
# !jupyter nbconvert --to html "Tarea2.ipynb"
# !jupyter nbconvert --to slides "Tarea2.ipynb"